package rank;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import system.Config;

public class GradeRandomSet {
	public Map<String, GradeRandomNode> nodeIndex = new HashMap<String, GradeRandomNode>();
	public LinkedList<GradeRandomNode> nodesOrderByTime = new LinkedList<GradeRandomNode>();

	public void addNode(GradeRandomNode n, long time) {
		GradeRandomNode node = nodeIndex.remove(n.guid);
		if (node != null) {
			nodesOrderByTime.remove(node);
		} else {
			node = n;
		}
		
		node.lastActiveTime = time;
		nodeIndex.put(node.guid, node);
		addToList(node);
//		nodes2.add(node);
		
		if (nodeIndex.size() > Config.RANDOM_GRADE_MAX) {
			node = nodesOrderByTime.iterator().next();
			nodeIndex.remove(node.guid);
			nodesOrderByTime.remove(node);
		}
	}
	
	public GradeRandomNode remove(String guid) {
		GradeRandomNode node = nodeIndex.remove(guid);
		if (node != null) {
			nodesOrderByTime.remove(node);
		} 
		return node;
	}

	public void selectRandom(String guid, Set<String> result, int count) {
		GradeRandomNode me = nodeIndex.remove(guid);
		Iterator<Entry<String, GradeRandomNode>> ite = nodeIndex.entrySet().iterator();
		Entry<String, GradeRandomNode> entry = null;
		int stepMax = nodeIndex.size() / count;
		if (stepMax == 0 && count > nodeIndex.size()) {
			while (ite.hasNext()) {
				result.add(ite.next().getKey());
			}
		} else {
			int step;
			for (int i = 0; i < count; i++) {
				step = (int)(Math.random()*stepMax) + 1;
				while (step > 0 && ite.hasNext()) {
					entry = ite.next();
					step--;
				}
				if (entry != null)
					result.add(entry.getKey());
			}
		}
		if (me != null) {
			nodeIndex.put(guid, me);
		}
	}
	
	public void addToList(GradeRandomNode node) {
		Iterator<GradeRandomNode> ite = nodesOrderByTime.iterator();
		GradeRandomNode before;
		int index = 0;
		while(ite.hasNext()) {
			before = ite.next();
			if (node.lastActiveTime < before.lastActiveTime) {
				nodesOrderByTime.add(index, node);
				return;
			}
			index++;
		}
		nodesOrderByTime.add(node);
	}
	
	public void print() {
		Iterator<GradeRandomNode> it = nodesOrderByTime.iterator();
		GradeRandomNode node;
		while (it.hasNext()) {
			node = it.next();
			System.out.println(node.lastActiveTime);
		}
	}
}
